package com.weblog.weblog.common.exception;

import com.weblog.weblog.common.enums.ResponseCodeEnum;
import com.weblog.weblog.common.utils.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * @author gc
 * @class_name GlobalExceptionHandler
 * @date 2023年09月13日 20:03
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /*
     * 自定义业务异常
     * @author gc
     * @date 2023/9/13 20:03
     * @param null
     * @return null
     */
    @ExceptionHandler({BizException.class})   //指定只捕获自定义异常
    @ResponseBody
    public Response<Object> handleBizException(HttpServletRequest request,BizException e){
        log.warn("{} request fail , errorCode : {} , errorMessage : {}",request.getRequestURL(),e.getErrorCode(),e.getErrorMessage());
        return Response.fail(e);
    }

    /*
     * 其他异常
     * @author gc
     * @date 2023/9/14 18:35
     * @param null
     * @return null
     */
    @ResponseBody
    @ExceptionHandler({Exception.class})
    public Response<Object> handleOtherException(HttpServletRequest request , Exception e){
        log.error("{} request error , " , request.getRequestURL() , e);
        return Response.fail(ResponseCodeEnum.SYSTEM_ERROR);
    }

    /*
     * 捕捉参数校验异常   MethodArgumentNotValidException类
     * @author gc
     * @date 2023/9/14 18:59
     * @param null
     * @return null
     */

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest request , MethodArgumentNotValidException e){
        //参数校验异常码
        String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();

        BindingResult bindingResult = e.getBindingResult();

        StringBuilder sb = new StringBuilder();

        //整合信息  包含不通过字段
        Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors -> errors.forEach(error ->
                sb.append(error.getField())
                        .append(" ")
                        .append(error.getDefaultMessage())
                        .append(", 当前值: '")
                        .append(error.getRejectedValue())
                        .append("'; ")
        ));

        String errorMessage = sb.toString();
        log.warn("{} request error , errorCode: {}, errorMessage: {}",request.getRequestURL(), errorCode, errorMessage);

        return Response.fail(errorCode , errorMessage);
    }


    @ExceptionHandler({ AccessDeniedException.class })
    public void throwAccessDeniedException(AccessDeniedException e) throws AccessDeniedException {
        // 捕获到鉴权失败异常，主动抛出，交给 RestAccessDeniedHandler 去处理
        log.info("=============> 捕获到 AccessDeniedException");
        throw e;
    }

}
